package com.kkb.robotcustomerservice.config;

import com.kkb.robotcustomerservice.entities.GeneralProblems;
import com.kkb.robotcustomerservice.service.GeneralProblemsService;
import com.kkb.robotcustomerservice.service.InvertedIndexService;
import com.kkb.robotcustomerservice.util.BM25Similarity;
import com.kkb.robotcustomerservice.util.JsonUtils;
import com.kkb.robotcustomerservice.util.WordsUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.CommandLineRunner;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;

import java.util.*;

@Component
//@Order(2)   //通过order值的大小来决定启动的顺序
public class BM25SimilarityConfig implements CommandLineRunner {
    @Autowired
    GeneralProblemsService generalProblemsService;

    @Autowired
    InvertedIndexService invertedIndexService;

    //得出模型
    private static BM25Similarity model;

    //在内存存储数据库所有数据
    private static List<GeneralProblems> problemsList;

    //倒排索引命中Key的个数的因子
    public static final double KEY = 0.75;

    //命中queId集合
    private static Map<Integer, Integer> queIdMap = new HashMap<>();

    //优化后queId集合
    private static List<Integer> queId = new ArrayList<>();

    /**
     * 传入string数据，遍历数据库得到答案和置信度
     * @param yourProblem 你的问题string
     * @return map（答案和置信度）
     */
    public Map getConfidence(String yourProblem){
        //对输入的数据进行分词
        List<String> questionListPart = WordsUtil.removeStop(WordsUtil.splitWords(yourProblem));
        //置信度
        double confidence = 0.0;
        //上一条相似度
        double preConfidence = 0.0;
        //答案ID
        Integer qid = null;

        askForLeave(yourProblem);

        //遍历数据库所有数据
        for (GeneralProblems problems: problemsList){
            //对所有数据进行分词
//            List<String> problemsList = WordsUtil.removeStop(WordsUtil.splitWords(problems.getContent()));
            List<String> problemsList = JsonUtils.jsonToList(problems.getParticiple(), String.class);
            //计算当前数据相似度
            preConfidence = model.similarity(questionListPart, problemsList);
            //计算出最大相似度（置信度）和他的ID
            if (preConfidence>confidence){
                confidence = preConfidence;
                qid = problems.getQueId();
            }
        }
        //存入map返回
        Map map = new HashMap();
        map.put("confidence",confidence);
        map.put("qid",qid);
        return map;
    }

    public static List<GeneralProblems> getProblemsList() {
        return problemsList;
    }

    public static BM25Similarity getModel() {
        return model;
    }

    @Override
    public void run(String... args) throws Exception {
//        askForLeave();
    }

    //倒排索引检索
    public void getQueIdList(String problem) {
        System.out.println("-------检索开始------");
        List<String> wordList = WordsUtil.removeStop(WordsUtil.splitWords(problem));
        for (String word : wordList) {
            List<Integer> queIdList = invertedIndexService.getQueId(word);
            if (queIdList != null && !queIdList.isEmpty()) {
                for (Integer queId : queIdList) {
                    if (queIdMap.containsKey(queId)) {
                        queIdMap.put(queId, queIdMap.get(queId) + 1);
                    } else {
                        queIdMap.put(queId, 1);
                    }
                }
            }
        }
        Set<Map.Entry<Integer, Integer>> entries = queIdMap.entrySet();
        for (Map.Entry<Integer, Integer> entry : entries) {
            if (entry.getValue() > KEY * wordList.size()) {
                queId.add(entry.getKey());
            }
        }
        System.out.println("-----检索完成-----");
    }

    public void askForLeave(String problems){
        System.out.println("---------------------正在生产算法模型，请等待------------------------");
        //启动倒排索引检索
        getQueIdList(problems);
        //获得相似问题数据
        problemsList = generalProblemsService.findProblems(queId);

        //获得所有通用问题数据
//        problemsList = generalProblemsService.findAllProblems();

        //分词列表
        List<String> wordList = WordsUtil.removeStop(WordsUtil.splitWords(problems));
        List<List<String>> list = new ArrayList<>();
        list.add(wordList);
        for (GeneralProblems problem : problemsList){
//            List<String> problemListPart = WordsUtil.removeStop(WordsUtil.splitWords(problem.getContent()));
            List<String> problemListPart = JsonUtils.jsonToList(problem.getParticiple(), String.class);
            list.add(problemListPart);
        }
        //引入分词列表得出模型
        model = new BM25Similarity(list);
        System.out.println("--------------算法模型初始化完成------------------");
    }
}
